package app.modules.infrastructure.profile.business.service;

import app.modules.common.constant.TenantConstants;
import app.modules.common.enums.EnableFlagEnum;
import app.modules.common.util.auth.CurrentSubjectUtil;
import app.modules.infrastructure.profile.constant.ProfileMsgConstants;
import app.modules.infrastructure.profile.dto.web.WebProfileDetailDTO;
import app.modules.infrastructure.profile.dto.web.WebProfileSettingDTO;
import app.modules.infrastructure.profile.dto.web.WebProfileSettingUpdateDTO;
import app.modules.infrastructure.profile.enums.LevelTypeEnum;
import app.modules.infrastructure.profile.persistence.dao.ProfileItemDAO;
import app.modules.infrastructure.profile.persistence.dao.ProfileValueDAO;
import app.modules.infrastructure.profile.persistence.entity.ProfileItemEO;
import app.modules.infrastructure.profile.persistence.entity.ProfileValueEO;
import jasmine.framework.common.exception.BusinessException;
import jasmine.framework.common.exception.DataNotFoundException;
import jasmine.framework.common.util.CheckUtil;
import jasmine.framework.common.util.CollectionUtil;
import jasmine.framework.common.util.I18nUtil;
import jasmine.framework.common.util.StringUtil;
import jasmine.framework.context.CurrentSubject;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * @author mh.z
 */
@Service
public class ProfileValueService implements IProfileValueService {
    private ProfileValueDAO profileValueDAO;
    private ProfileItemDAO profileItemDAO;

    public ProfileValueService(ProfileValueDAO profileValueDAO, ProfileItemDAO profileItemDAO) {
        this.profileValueDAO = profileValueDAO;
        this.profileItemDAO = profileItemDAO;
    }

    /**
     * 查询配置详情
     *
     * @param profileItemId
     * @return
     */
    public WebProfileDetailDTO getProfileDetailById(Long profileItemId) {
        CheckUtil.notNull(profileItemId, "profileItemId null");

        ProfileItemEO profileItemEO = profileItemDAO.getById(profileItemId);
        if (profileItemEO == null) {
            throw new DataNotFoundException(ProfileItemEO.class, profileItemId);
        }

        WebProfileDetailDTO detailDTO = new WebProfileDetailDTO();
        String profileItemCode = profileItemEO.getItemCode();
        // 配置项ID/代码/名称/描述
        detailDTO.setProfileItemId(profileItemId);
        detailDTO.setProfileItemCode(profileItemCode);
        detailDTO.setProfileItemName(profileItemEO.getItemName());
        detailDTO.setProfileItemDesc(profileItemEO.getItemDesc());

        Long tenantId = CurrentSubject.getTenantId();
        Long userId = CurrentSubject.getUserId();
        boolean adminFlag = CurrentSubjectUtil.isAdminUser();

        List<ProfileValueEO> profileValueList = profileValueDAO.listProfileValuesByProfileName(profileItemCode,
                tenantId, userId, false, false);
        Map<String, ProfileValueEO> profileValueMap = CollectionUtil
                .toMap(profileValueList, ProfileValueEO::getLevelType);

        // 应用设置
        WebProfileSettingDTO appSetting = createWebProfileSettingDTO(profileValueMap,
                LevelTypeEnum.APP.getCode(), !TenantConstants.SYSTEM_TENANT_ID.equals(tenantId));
        detailDTO.setAppSetting(appSetting);
        // 租户设置
        WebProfileSettingDTO tenantSetting = createWebProfileSettingDTO(profileValueMap,
                LevelTypeEnum.TENANT.getCode(), !adminFlag);
        detailDTO.setTenantSetting(tenantSetting);
        // 用户设置
        WebProfileSettingDTO userSetting = createWebProfileSettingDTO(profileValueMap,
                LevelTypeEnum.USER.getCode(), false);
        detailDTO.setUserSetting(userSetting);

        return detailDTO;
    }

    /**
     * 创建 WebProfileSettingDTO 对象
     *
     * @param levelTypeAndValues
     * @param levelType
     * @param readonlyFlag
     * @return
     */
    protected WebProfileSettingDTO createWebProfileSettingDTO(Map<String, ProfileValueEO> levelTypeAndValues,
                                                              String levelType, boolean readonlyFlag) {
        CheckUtil.notNull(levelTypeAndValues, "levelTypeAndValues null");
        CheckUtil.notNull(levelType, "levelType null");
        WebProfileSettingDTO profileSettingDTO = new WebProfileSettingDTO();

        ProfileValueEO profileValueEO = levelTypeAndValues.get(levelType);
        EnableFlagEnum enableFlagEnum;

        if (profileValueEO != null) {
            enableFlagEnum = EnableFlagEnum.parseValue(profileValueEO.getEnableFlag());

            profileSettingDTO.setValueCode(profileValueEO.getValueCode());
            profileSettingDTO.setRemark(profileValueEO.getRemark());

        } else {
            enableFlagEnum = EnableFlagEnum.FALSE;

            profileSettingDTO.setValueCode(null);
            profileSettingDTO.setRemark(null);
        }

        // 层次类型代码/描述
        LevelTypeEnum levelTypeEnum = LevelTypeEnum.parseCode(levelType);
        profileSettingDTO.setLevelType(levelType);
        profileSettingDTO.setLevelTypeDesc(I18nUtil.getMessage(levelTypeEnum));
        // 只读标志
        profileSettingDTO.setReadonlyFlag(readonlyFlag);
        // 启用标志
        profileSettingDTO.setEnableFlag(enableFlagEnum.getValue());
        profileSettingDTO.setEnableFlagDesc(I18nUtil.getMessage(enableFlagEnum));

        return profileSettingDTO;
    }

    /**
     * 更新配置值项
     *
     * @param updateDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateProfileValue(WebProfileSettingUpdateDTO updateDTO) {
        CheckUtil.notNull(updateDTO, "updateDTO null");
        Long profileItemId = CheckUtil.notNull(updateDTO.getProfileItemId(),
                "updateDTO.profileItemId null");
        String levelType = CheckUtil.notNull(updateDTO.getLevelType(),
                "updateDTO.levelType null");
        String valueCode = updateDTO.getValueCode();
        String remark = updateDTO.getRemark();
        Boolean enableFlag = updateDTO.getEnableFlag();

        // 查询配置项
        ProfileItemEO profileItemEO = profileItemDAO.getById(profileItemId);
        if (profileItemEO == null) {
            throw new DataNotFoundException(ProfileItemEO.class, profileItemId);
        }

        Long tenantId = CurrentSubject.getTenantId();
        Long userId = CurrentSubject.getUserId();
        boolean adminFlag = CurrentSubjectUtil.isAdminUser();
        String levelValue;

        if (LevelTypeEnum.APP.codeEquals(levelType)) {
            if (!TenantConstants.SYSTEM_TENANT_ID.equals(tenantId)) {
                throw new BusinessException(ProfileMsgConstants.ONLY_SYSTEM_TENANT_CAN_UPDATE_THE_PROFILE_VALUE, null);
            }

            levelValue = StringUtil.toString(TenantConstants.SYSTEM_TENANT_ID);
        } else if (LevelTypeEnum.TENANT.codeEquals(levelType)) {
            if (!adminFlag) {
                throw new BusinessException(ProfileMsgConstants.ONLY_TENANT_ADMIN_CAN_UPDATE_THE_PROFILE_VALUE, null);
            }

            levelValue = StringUtil.toString(tenantId);
        } else {
            levelValue = StringUtil.toString(userId);
        }

        String profileItemCode = profileItemEO.getItemCode();
        // 查询配置项值
        List<ProfileValueEO> profileValueList = profileValueDAO.listProfileValuesByProfileName(profileItemCode,
                tenantId, userId, false, false);
        Map<String, ProfileValueEO> profileValueMap = CollectionUtil
                .toMap(profileValueList, ProfileValueEO::getLevelType);
        ProfileValueEO profileValueEO = profileValueMap.get(levelType);

        // 新增/更新项值
        if (profileValueEO != null) {
            // 值代码
            profileValueEO.setValueCode(valueCode);
            // 备注
            profileValueEO.setRemark(remark);
            // 启用标志
            profileValueEO.setEnableFlag(enableFlag);

            profileValueDAO.strictUpdateById(profileValueEO);
        } else {
            profileValueEO = new ProfileValueEO();

            profileValueEO.setProfileItemId(profileItemId);
            // 层次类型/层次值
            profileValueEO.setLevelType(levelType);
            profileValueEO.setLevelValue(levelValue);
            // 值代码/备注/启用标志
            profileValueEO.setValueCode(valueCode);
            profileValueEO.setRemark(remark);
            profileValueEO.setEnableFlag(enableFlag);
            // 租户ID
            profileValueEO.setTenantId(tenantId);

            profileValueDAO.save(profileValueEO);
        }
    }

}
